// Copyright (C) 1953-2022 NUDT
// Verilog module name - opensync_protocol_decapsulate
// Version: V4.1.0.20221206
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         opensync_frame_decapsulation
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module opensync_protocol_decapsulate(
        i_clk,
        i_rst_n,
       
        iv_data,
        i_data_wr,
        
        ov_local_cnt_rx,
		ov_local_cnt_tx,
		ov_eth_type,
        ov_tsmp_type,
		ov_tsmp_subtype,
		ov_osm_id      ,
           
        ov_data,
        o_data_wr
    );
// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n;
//input
(*MARK_DEBUG="ture"*)input       [8:0]       iv_data;
(*MARK_DEBUG="ture"*)input                   i_data_wr;
//output
output  reg [39:0]      ov_local_cnt_rx;
output  reg [39:0]      ov_local_cnt_tx;
output  reg [15:0]      ov_eth_type;
output  reg [7:0]       ov_tsmp_type;
output  reg [7:0]       ov_tsmp_subtype;
output  reg [7:0]       ov_osm_id;

output  reg [8:0]       ov_data;
output  reg             o_data_wr;
//***************************************************
//   add valid of data and delay 15 cycles
//***************************************************
//internal wire
reg         [134:0]     rv_data;
reg         [10:0]      rv_byte_cnt; 
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n) begin
        rv_data      <= 135'b0;
        rv_byte_cnt  <= 11'b0;
    end
    else begin
        if(i_data_wr)begin
            rv_byte_cnt <= rv_byte_cnt +1'b1;
            rv_data     <= {rv_data[125:0],iv_data};
        end
        else begin
            rv_data     <= {rv_data[125:0],9'b0};  
            rv_byte_cnt <= 11'b0;           
        end
    end
end            
//***************************************************
//         opensync protocol decapsulate
//***************************************************    
reg         [1:0]       rv_opd_state;
localparam  IDLE_S             = 2'd0,
            EXTRACT_TIME_S     = 2'd1,
            TRAN_PKT_S         = 2'd2; 
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        ov_data             <= 9'b0;
        o_data_wr           <= 1'b0;
		
        ov_local_cnt_rx		<= 40'b0;
		ov_local_cnt_tx     <= 40'b0;
		ov_eth_type     	<= 16'b0;
		ov_tsmp_type        <= 8'b0 ;
		ov_tsmp_subtype     <= 8'b0 ;
		ov_osm_id           <= 8'b0 ;
        rv_opd_state        <= IDLE_S;
    end
    else begin
        case(rv_opd_state)
            IDLE_S:begin
                ov_local_cnt_rx			<= 40'b0;
                ov_local_cnt_tx         <= 40'b0;				
                if(rv_byte_cnt == 11'd15)begin
					ov_eth_type     	<= {rv_data[25:18],rv_data[16:9]};
					ov_tsmp_type        <= rv_data[7:0] ;
					ov_tsmp_subtype     <= iv_data[7:0] ; 
                    ov_osm_id           <= 8'b0 ;					
                    if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06))begin//opensync.
                        if((iv_data[7:0] == 8'h01)||(iv_data[7:0] == 8'h02)||(iv_data[7:0] == 8'h03)||(iv_data[7:0] == 8'h04)||(iv_data[7:0] == 8'h07)||(iv_data[7:0] == 8'h08)||(iv_data[7:0] == 8'h09))begin//Sync、Pdelay_req、Pdelay_resp、Pdelay_resp_follow_up、follow_up、signaling和announce封装报文
						    o_data_wr           <= 1'b0;
						    ov_data             <= 9'b0;	                        
                            rv_opd_state        <= EXTRACT_TIME_S;
					    end
						else begin
							o_data_wr           <= 1'b1;
							ov_data             <= rv_data[134:126];	                        
                            rv_opd_state        <= TRAN_PKT_S;
						end
					end 
                    else begin
                        o_data_wr           <= 1'b1;
						ov_data             <= rv_data[134:126];																
                        rv_opd_state        <= TRAN_PKT_S;
					end
                end
				else begin
                    o_data_wr               <= 1'b0;
					ov_data 	            <= 9'b0;
					
					ov_eth_type     	    <= 16'b0;
					ov_tsmp_type            <= 8'b0 ;
					ov_tsmp_subtype         <= 8'b0 ;
					ov_osm_id               <= 8'b0 ;
					
                    rv_opd_state            <= IDLE_S;                
                end
            end							
            EXTRACT_TIME_S:begin          
                if(rv_byte_cnt  == 11'd31)begin                
					o_data_wr               <= 1'b0;
					ov_data                 <= 9'b0;                      
					ov_osm_id               <= rv_data[133:126] ;
					ov_local_cnt_rx		    <= {rv_data[106:99],rv_data[97:90],rv_data[88:81],rv_data[79:72],rv_data[70:63]};//receive time;
                    ov_local_cnt_tx         <= {rv_data[61:54],rv_data[52:45],rv_data[43:36],rv_data[34:27],rv_data[25:18]};//transmit time;				
                    rv_opd_state            <= EXTRACT_TIME_S;               
                end
                else if(rv_byte_cnt  == 11'd47)begin
					o_data_wr               <= 1'b1;
					ov_data                 <= {1'b1,rv_data[133:126]};   				
				
                    rv_opd_state            <= TRAN_PKT_S;
                end
                else begin
					o_data_wr               <= 1'b0;
					ov_data                 <= 9'b0;  
				
                    rv_opd_state            <= EXTRACT_TIME_S;
                end
            end
            TRAN_PKT_S:begin   
				o_data_wr       <= 1'b1;
				ov_data         <= rv_data[134:126];                
				if(rv_data[134]) begin   //transmit data.
                    rv_opd_state    <= IDLE_S;
                end
                else begin
                    rv_opd_state    <= TRAN_PKT_S;
                end
            end    
            default:begin
                ov_data             <= 8'b0;
                o_data_wr           <= 1'b0;
                rv_opd_state        <= IDLE_S;
            end
        endcase
    end
end    
endmodule